package cn.com.bluemoon.daps.standard.controller;


import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.enums.AuditStatus;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.exception.DapThrowException;
import cn.com.bluemoon.daps.common.mp.IBmService;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.common.webhook.Authors;
import cn.com.bluemoon.daps.model.entity.DapDataModel;
import cn.com.bluemoon.daps.standard.entity.*;
import cn.com.bluemoon.daps.standard.service.DapSystemAuditService;
import cn.com.bluemoon.daps.standard.vo.SysAuditReportFieldSearchVo;
import cn.com.bluemoon.daps.standard.vo.SysAuditReportSearchVo;
import cn.com.bluemoon.daps.standard.vo.SystemAuditSearchVo;
import cn.com.bluemoon.daps.system.dto.SystemInfoDto;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static cn.com.bluemoon.daps.standard.service.impl.DapSystemAuditServiceImpl.*;

/**
 * <p>
 * 系统稽核入口 前端控制器
 * </p>
 *
 * @author admin
 * @since 2020-08-04
 */
@Api(tags = {"系统稽核"})
@RestController
@Slf4j
@Authors(value = @Authors.Author(name = "Jarod.Kong", desc = "系统稽核列表", devTime = ""))
@RequestMapping("/dapAuditSystem")
public class DapStandardSystemAuditController {

    @Resource
    DapSystemAuditService dapSystemAuditService;

    @BmPermission(value = {"system:audit:query"}, name = "系统稽核列表查询")
    @PostMapping("/sysAudit/list")
    @ApiOperation(value = "获取系统数据系统稽核列表数据")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = SystemInfoDto.class)})
    public ResultBean<?> findSysAuditListPage(@RequestBody SystemAuditSearchVo auditSearchVo) {
        IPage<SystemInfoDto> list = dapSystemAuditService.findSysAuditListPage(auditSearchVo);
        return IBmService.toAntDvPageTool(list);
    }

    @BmPermission(value = {"system:audit:start"}, name = "系统稽核-发起稽核")
    @PostMapping("/sysAudit/generateReport")
    @ApiOperation(value = "发起稽核，生成报告")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<?> generateReport(@RequestParam("systemId") String systemId) {
        dapSystemAuditService.setSysAuditStatus(systemId, AuditStatus.AUDIT_DOING, false);
        try {
            dapSystemAuditService.startAuditBySysId(systemId);
        } catch (Exception e) {
            log.error("生成报告异常，调整状态为待稽核", e);
            dapSystemAuditService.setSysAuditStatus(systemId, AuditStatus.AUDIT_WAIT, false);
            if (e instanceof DapException) {
                throw e;
            } else {
                throw new DapException("生成报告异常！！！");
            }
        }
        return ResultBean.ok();
    }

    /**
     * @param sysAuditId {@link cn.com.bluemoon.daps.system.entity.DapSystemInfo#getAuditResultId()}
     * @return ResultBean<?>
     */
    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告")
    @PostMapping("/sysAudit/report/list")
    @ApiOperation(value = "根据系统稽核id,系统稽核报告列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapAuditSystemResult.class)})
    public ResultBean<?> findSysAuditReportList(@RequestParam @Valid @NotBlank(message = "系统稽核id不可为空") String sysAuditId) {
        List<DapAuditSystemResult> list = dapSystemAuditService.findAuditSystemResultList(sysAuditId);
        return ResultBean.ok(list);
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告")
    @GetMapping("/sysAudit/model/list")
    @ApiOperation(value = "根据系统稽核id,获取报告相关的模型信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<?> findModelInfosBySysAuditId(@RequestParam @Valid @NotBlank(message = "系统稽核id不可为空") String systemId) {
        List<DapDataModel> list = dapSystemAuditService.findModelInfosBySystemId(systemId);
        return ResultBean.ok(list);
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告")
    @PostMapping("/sysAudit/chineseReports")
    @ApiOperation(value = "根据系统稽核id和对应模型id,系统稽核中文检查对应的表报告列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapAuditChinResult.class)})
    public ResultBean<?> findAuditSystemAuditChinResults(@RequestBody SysAuditReportSearchVo<DapAuditChinResult> searchV) {
        IPage<DapAuditChinResult> list = dapSystemAuditService.findAuditSystemAuditChinResults(searchV);
        return IBmService.toAntDvPageTool(list);
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告")
    @PostMapping("/sysAudit/chineseReport/fields")
    @ApiOperation(value = "根据统稽核中文检查id,系统稽核中文检查对应表的字段报告列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapAuditFieldChinResult.class)})
    public ResultBean<?> findAuditFieldChinResults(@RequestBody SysAuditReportFieldSearchVo<DapAuditFieldChinResult> searchVo) {
        IPage<DapAuditFieldChinResult> list = dapSystemAuditService.findAuditFieldChinResults(searchVo);
        return IBmService.toAntDvPageTool(list);
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告", queryTokenPerm = true)
    @GetMapping("/sysAudit/chineseReport/export")
    @ApiOperation(value = "根据系统稽核id和模型id，导出相关不符合的中文报告信息-sheet1")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Void.class)})
    public void exportAuditChinResults(HttpServletResponse response, @RequestParam String sysAuditId,
                                       @RequestParam String modelId) {
        SysAuditReportSearchVo<DapAuditChinResult> searchVo = new SysAuditReportSearchVo<>();
        searchVo.setSysAuditId(sysAuditId);
        searchVo.setModelId(modelId);
        Workbook workbook = dapSystemAuditService.exportAuditChinResults(searchVo, EXPORT_CHI_RESULT_KEY);
        commonDownload(response, workbook, EXPORT_CHI_RESULT_KEY);
    }


    /**
     * 针对下载excel文件的方式（流）
     *
     * @param response
     * @param workbook
     * @param fileName
     */
    public static void commonDownload(HttpServletResponse response, Workbook workbook, String fileName) {
        try {
            BmAssetUtils.notNull(workbook, "文档对象不为空！！");
            String fileEncode = StandardCharsets.UTF_8.name();
            // 告诉浏览器输出内容为流
            response.setHeader("Content-Type", "application/octet-stream;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ";filename*=utf-8''"
                    + URLEncoder.encode(fileName, fileEncode));
            ServletOutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException ex) {
            log.error("下载文件异常", ex);
            throw new DapThrowException("下载文件异常," + ex.getMessage());
        } finally {
            try {
                workbook.close();
            } catch (IOException e) {
                log.error("下载文件异常", e);
            }
        }
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告", queryTokenPerm = true)
    @GetMapping("/sysAudit/chineseFieldReport/export")
    @ApiOperation(value = "根据系统稽核id和模型id，导出相关不符合的中文报告信息-sheet2")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Void.class)})
    public void exportAuditFieldChinResults(HttpServletResponse response, @RequestParam String sysAuditId,
                                            @RequestParam String modelId) {
        SysAuditReportSearchVo<DapAuditChinResult> searchVo = new SysAuditReportSearchVo<>();
        searchVo.setSysAuditId(sysAuditId);
        searchVo.setModelId(modelId);
        Workbook workbook = dapSystemAuditService.exportAuditChinResults(searchVo, EXPORT_CHI_FIELD_RESULT_KEY);
        commonDownload(response, workbook, EXPORT_CHI_FIELD_RESULT_KEY);
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告")
    @PostMapping("/sysAudit/standardReports")
    @ApiOperation(value = "根据系统稽核id和对应模型id,系统稽核标准检查对应的表报告列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapAuditStandardResult.class)})
    public ResultBean<?> standardReports(@RequestBody SysAuditReportSearchVo<DapAuditStandardResult> searchV) {
        IPage<DapAuditStandardResult> list = dapSystemAuditService.findAuditSystemAuditStdResults(searchV);
        return IBmService.toAntDvPageTool(list);
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告")
    @PostMapping("/sysAudit/standardReport/fields")
    @ApiOperation(value = "根据统稽核标准检查id,系统稽核标准检查对应表的字段报告列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapAuditFieldStandardResult.class)})
    public ResultBean<?> findAuditFieldStdResults(@RequestBody SysAuditReportFieldSearchVo<DapAuditFieldStandardResult> searchVo) {
        IPage<DapAuditFieldStandardResult> list = dapSystemAuditService.findAuditFieldStdResults(searchVo);
        return IBmService.toAntDvPageTool(list);
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告", queryTokenPerm = true)
    @GetMapping("/sysAudit/stdReport/export")
    @ApiOperation(value = "根据系统稽核id和模型id，导出相关不符合的标准报告信息-sheet1")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Void.class)})
    public void exportAuditStdResults(HttpServletResponse response, @RequestParam String sysAuditId,
                                      @RequestParam String modelId) {
        SysAuditReportSearchVo<DapAuditStandardResult> searchVo = new SysAuditReportSearchVo<>();
        searchVo.setSysAuditId(sysAuditId);
        searchVo.setModelId(modelId);
        Workbook workbook = dapSystemAuditService.exportAuditStdResults(searchVo, EXPORT_STD_RESULT_KEY);
        commonDownload(response, workbook, EXPORT_STD_RESULT_KEY);
    }

    @BmPermission(value = {"system:audit:view"}, name = "系统稽核-查看报告", queryTokenPerm = true)
    @GetMapping("/sysAudit/stdFieldReport/export")
    @ApiOperation(value = "根据系统稽核id和模型id，导出相关不符合的标准报告信息-sheet2")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Void.class)})
    public void exportAuditStdChinResults(HttpServletResponse response, @RequestParam String sysAuditId,
                                          @RequestParam String modelId) {
        SysAuditReportSearchVo<DapAuditStandardResult> searchVo = new SysAuditReportSearchVo<>();
        searchVo.setSysAuditId(sysAuditId);
        searchVo.setModelId(modelId);
        Workbook workbook = dapSystemAuditService.exportAuditStdResults(searchVo, EXPORT_STD_FIELD_RESULT_KEY);
        commonDownload(response, workbook, EXPORT_STD_FIELD_RESULT_KEY);
    }


}
